package com.wondertek.poms.pre.manager.filter;

import cn.hutool.core.collection.CollectionUtil;

import com.alibaba.fastjson.JSON;
import com.wondertek.poms.common.constant.Constants;
import com.wondertek.poms.core.filter.*;
import com.wondertek.poms.core.filter.impl.*;
import com.wondertek.poms.core.service.IPcProductRuleService;
import com.wondertek.poms.dao.po.Content;
import com.wondertek.poms.dao.po.PcProductRule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p><b>ProductInfoRuleManager Description:</b> 二级产品规则过滤</p>
 * @author douzi
 * <b>DATE</b> 2020年12月22日 下午6:44:23
 */
@Slf4j
@Component
public class ProductInfoRuleManager {

    @Autowired
    private IPcProductRuleService pcProductRuleService;

    /**
     * <p><b>Title:</b> passProductRule </p>
     * <p><b>Description:</b> 判断二级产品的规则是否符合;
     * 限制入包条件：限制规则存在，并且符合限制规则；或者限制规则不存在；然后已选规则存在，且不符合已选规则；反之结束流程
     * </p>
     *
     * @param vo
     * @param productId
     * @return false 表示没通过  true表示通过规则
     * @author douzi
     */
    public boolean passProductRule(Content vo, Long productId) {
        Map<Integer, List<PcProductRule>> prsMap = getProductRuleMap(productId);
        List<PcProductRule> limitRules = prsMap.get(Constants.PRODUCT_RULE_TYPE_2);
        if (CollectionUtil.isNotEmpty(limitRules)) {
            log.info("二级产品规则|业务数据：" + vo.getContentId() + "|媒资ID:" + vo.getAssetId() + "|入包二级产品:" + productId + "|限制规则数量:" + limitRules.size());
            if (isMatchLimitRule(vo, limitRules)){
                return false;
            }
        }

        List<PcProductRule> selectRules = prsMap.get(Constants.PRODUCT_RULE_TYPE_1);
        if (selectRules == null){
            return true;
        }
        log.info("二级产品规则|业务数据：" + vo.getContentId() + "|媒资ID:" + vo.getAssetId() + "|入包二级产品:" + productId + "|已选规则数量:" + selectRules.size());
        return isMatchSelectRule(vo, selectRules);
    }


    public Map<Integer, List<PcProductRule>> getProductRuleMap(Long secondId) {
        List<PcProductRule> prs = pcProductRuleService.findRuleBySecondId(secondId);
        Map<Integer, List<PcProductRule>> map = new HashMap<>();
        prs.forEach(r -> {
            List<PcProductRule> partPrs = null;
            int ruleTypeInt = Integer.parseInt(r.getRuleType());
			if (!map.containsKey(ruleTypeInt)) {
                partPrs = new ArrayList<>();
            } else {
                partPrs = map.get(ruleTypeInt);
            }

            if (ruleTypeInt == Constants.PRODUCT_RULE_TYPE_1 || ruleTypeInt == Constants.PRODUCT_RULE_TYPE_2) {
                partPrs.add(r);
                map.put(ruleTypeInt, partPrs);
            }
        });

        return map;
    }
    
	public static void main(String[] args) {
		List<PcProductRule> prs = new ArrayList<>();
		PcProductRule a = new PcProductRule();
		a.setRuleType("1");
		PcProductRule b = new PcProductRule();
		b.setRuleType("2");
		PcProductRule c = new PcProductRule();
		c.setRuleType("2");
		prs.add(a);
		prs.add(b);
		prs.add(c);
		
		Map<Integer, List<PcProductRule>> map = new HashMap<>();
		prs.forEach(r -> {
			List<PcProductRule> partPrs = null;
			int ruleTypeInt = Integer.parseInt(r.getRuleType());
			if (!map.containsKey(ruleTypeInt)) {
				partPrs = new ArrayList<>();
			} else {
				partPrs = map.get(ruleTypeInt);
			}

			if (ruleTypeInt == Constants.PRODUCT_RULE_TYPE_1 || ruleTypeInt == Constants.PRODUCT_RULE_TYPE_2) {
				partPrs.add(r);
				map.put(ruleTypeInt, partPrs);
			}
		});
		
		System.out.println(JSON.toJSONString(map));
	}

    /**
     * <p><b>Title:</b> isMatchLimitRule</p>
     * <p><b>Description:</b> 是否匹配二级产品限制规则</p>
     *
     * @param vo
     * @param limitRules
     * @return
     * @author douzi
     */
    private boolean isMatchLimitRule(Content vo, List<PcProductRule> limitRules) {
        boolean isMatch = false;

        for (PcProductRule limitRule : limitRules) {
            isMatch = contentFilter(limitRule, vo, true);
            if (isMatch){
                break;
            }
        }
        return isMatch;
    }

    /**
     * <p><b>Title:</b> isMatchSelectRule</p>
     * <p><b>Description:</b> 是否匹配二级产品已选规则</p>
     *
     * @param vo
     * @param selectRules
     * @return
     * @author douzi
     */
    private boolean isMatchSelectRule(Content vo, List<PcProductRule> selectRules) {
        boolean isMatch = false;

        for (PcProductRule selectRule : selectRules) {
            isMatch = contentFilter(selectRule, vo, false);
            if (isMatch){
                break;
            }
        }
        return isMatch;
    }

    /**
     * <p><b>Title:</b> contentFilter</p>
     * <p><b>Description:</b> 二级产品规则过滤</p>
     *
     * @param rule    二级产品规则
     * @param vo      接收的内容vo
     * @param isLimit 是否是限制规则
     * @return
     * @author douzi
     */
    public boolean contentFilter(PcProductRule rule, Content vo, boolean isLimit) {
        RuleFilterChain rfc = new RuleFilterChain();

        if(isLimit){
            rfc.addFilter(new CopyRightBlackAreaFilter());
        }else{
            rfc.addFilter(new CopyRightWhiteAreaFilter());
        }
        rfc.addFilter(new CopyRightCpIdFilter())
                .addFilter(new CopyRightTerminalFilter())
                .addFilter(new CopyRightScopeFilter())
                .addFilter(new CopyRightTypeFilter())
                .addFilter(new AuthorizationWayFilter())
                .addFilter(new NeedDRMFilter())
                .doFilter(rule, vo, rfc);

        if (rfc.isFlag()) {
            log.info("二级产品规则|业务数据：" + vo.getContentId() + "|assetId:" + vo.getAssetId() + "|二级产品ID:" + rule.getProductInfoPackageId() + "| 符合" + (isLimit ? "二级产品限制规则" : "二级产品已选规则") + "|" + rule.toString());
        } else {
            log.info("二级产品规则|业务数据：" + vo.getContentId() + "|assetId:" + vo.getAssetId() + "|二级产品ID:" + rule.getProductInfoPackageId() + "| 不符合" + (isLimit ? "二级产品限制规则" : "二级产品已选规则") + "|" + rfc.getResultStr().toString());
        }
        return rfc.isFlag();
    }
}
